package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

func functestmain() {
	quere := make(chan string, 2)
	quere <- "one"
	quere <- "two"
	close(quere)
	for msg := range quere {
		fmt.Println("111", msg)
	}
	for msg := range quere {
		fmt.Println("222", msg)
	}
	for msg := range quere {
		fmt.Println("333", msg)
	}

	for {
		msg, ok := <-quere
		if !ok {
			break // 通道关闭并且值已被接收完毕
		}
		fmt.Println("111", msg)
	}

	//timer1 := time.NewTimer(time.Second * 2)
	//<-timer1.C
	//fmt.Println("timer1  111")
	//
	//timer2 := time.NewTimer(time.Second)
	//select {
	//case <-timer2.C:
	//	fmt.Println("timer2 222 222222222")
	//}
	//fmt.Println("timer2  222")
	//// 启动新的 Timer 3，避免使用已触发的 timer2
	//timer3 := time.NewTimer(1 * time.Second)
	//go func() {
	//	<-timer3.C
	//	fmt.Println("timer3 333")
	//}()
	//
	//stop2 := timer3.Stop()
	//if stop2 {
	//	fmt.Println("timer4  444")
	//}
	sd8()
}
func sd() {
	timer2 := time.NewTimer(time.Second * 3)
	fmt.Println("timer2  333", timer2, "======", time.Now())
	for {
		<-timer2.C
		fmt.Println("timer2  444", timer2, "======", time.Now())
	}
}
func sd2() {
	ticker := time.NewTicker(time.Millisecond * 100)
	done := make(chan bool)
	go func() {
		select {
		case <-done:
			return
		case <-ticker.C:
			fmt.Println("timer2  555", time.Now())
		}
	}()
	time.Sleep(time.Second)

	ticker.Stop()
	done <- true
	fmt.Println("timer2  666", time.Now())
}

// 线程等待
func works(id int) {
	fmt.Println("works begin !", id)
	time.Sleep(time.Millisecond * time.Duration(100*id))
	fmt.Println("works end !", id)
}
func sd3() {
	var wg sync.WaitGroup
	for i := 1; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			works(i)
		}()
	}
	wg.Wait()
	fmt.Println("sd3 sd3 !", time.Now())
}
func sd4() {
	var respose = make(chan string, 3)
	for i := 1; i <= 3; i++ {
		respose <- fmt.Sprintf("%d", i)
	}
	close(respose)
	limi := time.Tick(time.Millisecond * 200)
	for msg := range respose {
		<-limi
		fmt.Println("limi :", msg)
	}
	bursty := make(chan time.Time, 3)
	for i := 0; i < 3; i++ {
		bursty <- time.Now()
		fmt.Println("time.Now()  :", time.Now())
	}
	go func() {
		for t := range time.Tick(time.Millisecond * 200) {
			bursty <- t
			fmt.Println("go func time :", t)
		}
	}()
	go func() {
		bursty <- time.Now()
		fmt.Println("go func time :", time.Now())
	}()
	burstyint := make(chan int, 3)
	for i := 0; i < 3; i++ {
		burstyint <- i
	}
	close(burstyint)
	for msg := range burstyint {
		<-bursty
		<-limi
		fmt.Println("bursty", msg)
	}

}

//	go func() {
//		for t := range time.Tick(time.Millisecond * 10) {
//			bursty <- t
//			fmt.Println("go func time :", t)
//		}
//	}()
func sd6() {
	var ops atomic.Uint64
	var wg sync.WaitGroup
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < 1000; j++ {
				ops.Add(1)
			}
		}()
	}
	wg.Wait()
	fmt.Println("ops:", ops.Load())

}

type Cons struct {
	mu       sync.Mutex
	counters map[string]int
}

func (c *Cons) Incr(key string) {
	c.mu.Lock()
	c.counters[key]++
	defer c.mu.Unlock()
}
func sd7() {
	c := Cons{counters: map[string]int{"a": 0, "b": 1}}

	var wg sync.WaitGroup
	doint := func(name string, n int) {
		for i := 0; i < n; i++ {
			c.Incr(name)
			fmt.Println(name, "======", i)
		}
		wg.Done()
	}
	wg.Add(3)
	go doint("a", 1000)
	go doint("b", 2000)
	go doint("c", 3000)
	wg.Wait()
	fmt.Println(c.counters)
}

type readOp struct {
	key  int
	resp chan int
}
type writeOp struct {
	key  int
	val  int
	resp chan bool
}

func sd8() {
	var readOps uint64
	var writeOps uint64
	reads := make(chan readOp)
	writes := make(chan writeOp)
	go func() {
		var state = make(map[int]int)
		for true {
			select {
			case read := <-reads:
				read.resp <- state[read.key]
			case write := <-writes:
				state[write.key] = write.val
				write.resp <- true
			}
		}
	}()

	for w := 0; w < 10; w++ {
		go func() {
			for true {
				re := readOp{
					key:  w,
					resp: make(chan int),
				}
				reads <- re
				<-re.resp
				atomic.AddUint64(&readOps, 1)
				time.Sleep(time.Millisecond)
			}
		}()
	}

	for w := 0; w < 10; w++ {
		go func() {
			for true {
				write := writeOp{
					key:  w,
					val:  w,
					resp: make(chan bool),
				}
				writes <- write
				<-write.resp
				atomic.AddUint64(&writeOps, 1)
				time.Sleep(time.Millisecond)
			}
		}()
	}

	time.Sleep(time.Second)

	readOpsFinal := atomic.LoadUint64(&readOps)
	fmt.Println("readOps:", readOpsFinal)
	writeOpsFinal := atomic.LoadUint64(&writeOps)
	fmt.Println("writeOps:", writeOpsFinal)

}
